package org.ipmsg.core;

import java.io.UnsupportedEncodingException;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

public class Message {

    private byte packet[];//已转为字节数组的消息序列
    private long version;//当前版本
    private long serial;
    private long command;
    private String sysuser;
    private String host;
    private String content;
    private Attachment attachment;

    public Message() {
    }

    public Message(long version, long serial, String sysuser, String host, long command, String content, Attachment attachment) {
        this.version = version;
        this.serial = serial;
        this.sysuser = sysuser;
        this.host = host;
        this.command = command;
        this.content = content;
        this.attachment = attachment;
    }

    public Message(byte packet[]) {
        this.packet = packet;
        unpacked();
    }

    /**
     * 消息序列化
     */
    private void packed() {
        StringBuffer strbuf = new StringBuffer();
        strbuf.append(Long.toString(version)).append(":");
        strbuf.append(Long.toString(serial)).append(":");
        strbuf.append(sysuser).append(":");
        strbuf.append(host).append(":");
        strbuf.append(Long.toString(command)).append(":");
        strbuf.append(content);
        strbuf.append(Protocol.MSGFILE_SEPARATOR);
        if (attachment != null) {
            strbuf.append(attachment.getStringAttachment());
        }
        strbuf.append(Protocol.MSGFILE_SEPARATOR);
        String tmpstr = new String(strbuf);
        String ls = System.getProperty("line.separator", "\n");
        String cr = "\n";
        tmpstr = replaceString(tmpstr, ls, cr);
        try {
            //编码
            packet = tmpstr.getBytes("GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * 消息反序列化
     */
    private void unpacked() {
        String tmpstr = "";
        try {
            tmpstr = new String(packet, "GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String ls = System.getProperty("line.separator", "\n");
        String cr = "\n";
        tmpstr = replaceString(tmpstr, ls, cr).trim();
        StringTokenizer tokenizer = new StringTokenizer(tmpstr, ":", false);
        try {
            version = Long.parseLong(tokenizer.nextToken());
            serial = Long.parseLong(tokenizer.nextToken());
            sysuser = tokenizer.nextToken();
            host = tokenizer.nextToken();
            command = Long.parseLong(tokenizer.nextToken());
        } catch (NoSuchElementException ex) {
            return;
        } catch (NumberFormatException ex) {
            return;
        }
        //此处使用\f作为新的分割符，是为了让tokenizer返回剩下字符串，而不用":"是因为内容和附件中也会存在":"
        //故在内容和附件之间用的是"\0"这一特殊字符。
        String other = tokenizer.nextToken("\f").substring(1);
        tokenizer = new StringTokenizer(other, Protocol.MSGFILE_SEPARATOR, false);
        if (!other.startsWith(Protocol.MSGFILE_SEPARATOR) && tokenizer.hasMoreTokens()) {
            content = tokenizer.nextToken();
        }
        String attach = "";
        if (tokenizer.hasMoreTokens()) {
            attach = tokenizer.nextToken();
        }
        attachment = new Attachment(attach);
    }

    public boolean compare(Message argpack) {
        if (argpack == null) {
            return false;
        }
        return sysuser.equals(argpack.getSysUser()) && host.equals(argpack.getHost()) && serial == argpack.getSerial() && command == argpack.getCommand();
    }

    public byte[] getBytes() {
        packed();
        return packet;
    }

    public void setBytes(byte packet[]) {
        this.packet = packet;
        unpacked();
    }

    public void setVersion(long version) {
        this.version = version;
    }

    public long getVersion() {
        return version;
    }

    public long getSerial() {
        return serial;
    }

    public void setSerial(long serial) {
        this.serial = serial;
    }

    public String getSysUser() {
        return sysuser;
    }

    public void setSysUser(String user) {
        sysuser = user;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setCommand(long command) {
        this.command = command;
    }

    public long getCommand() {
        return command;
    }

    public String getContent() {
        return content != null ? content : "";
    }

    public Attachment getAttachment() {
        return attachment;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setAttachment(Attachment attachment) {
        this.attachment = attachment;
    }

    @Override
    public String toString() {
        return (new StringBuilder("[")).append(version).append(":").append(serial).append(":").append(sysuser).append(":").append(host).append(":").append(command).append(":").append(content).append("]").append(attachment.toString()).toString();
    }

    public String replaceString(String src, String before, String after) {
        if (src == null || src.isEmpty()) {
            return src;
        }
        if (before == null || before.isEmpty()) {
            return src;
        }
        StringBuffer sb = new StringBuffer();
        int oldidx = 0;
        for (int idx = src.indexOf(before); idx != -1; idx = src.indexOf(before, oldidx)) {
            sb.append(src.substring(oldidx, idx)).append(after);
            oldidx = idx + before.length();
        }

        if (oldidx < src.length()) {
            sb.append(src.substring(oldidx));
        }
        return sb.toString();
    }
}
